home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / MacPerl 5.1.3 / Mac_Perl_513_src / MacPerl5 / MPEditions.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-17  |  39.0 KB  |  1,432 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPEditions.c    -
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPEditions.c,v $
  12. Revision 1.2  1994/05/04  02:50:54  neeri
  13. Fix segment names.
  14.  
  15. Revision 1.1  1994/02/27  23:00:31  neeri
  16. Initial revision
  17.  
  18. Revision 0.3  1993/09/18  00:00:00  neeri
  19. Runtime
  20.  
  21. Revision 0.2  1993/05/30  00:00:00  neeri
  22. Support Console Windows
  23.  
  24. Revision 0.1  1993/05/29  00:00:00  neeri
  25. Compiles correctly
  26.  
  27. *********************************************************************/
  28.  
  29. #include <OSUtils.h>
  30. #include <Resources.h>
  31. #include <Errors.h>
  32. #include <AppleEvents.h>
  33.  
  34. #include "MPEditions.h"
  35.  
  36. #ifdef EVIL_USELESS_EDITIONS
  37. /**-----------------------------------------------------------------------
  38.         Name:         GetERefCon
  39.         Purpose:        Return the sectHandle (our own type) stored in
  40.                         the refcon of the SectionRecord.
  41.     -----------------------------------------------------------------------**/
  42.  
  43. #if !defined(powerc) && !defined(__powerc)
  44. #pragma segment Editions
  45. #endif
  46.  
  47. pascal SectHandle GetERefCon(SectionHandle EMSection)
  48. {
  49.     SectHandle aSectHandle;
  50.  
  51.     aSectHandle = (SectHandle)(*EMSection)->refCon;
  52.     return(aSectHandle);
  53. }
  54.  
  55. /**-----------------------------------------------------------------------
  56. Name:         SetERefCon
  57. Purpose:        Store a handle to our own SectRecord in the refcon
  58.                 field of the SectionRecord.
  59. -----------------------------------------------------------------------**/
  60.  
  61. #if !defined(powerc) && !defined(__powerc)
  62. #pragma segment Editions
  63. #endif
  64.  
  65. pascal void SetERefCon(SectionHandle EMSection, SectHandle aSectHandle)
  66. {
  67.     (*EMSection)->refCon = (long)aSectHandle;
  68. }
  69.  
  70. /**-----------------------------------------------------------------------
  71.         Name:         AddSection
  72.         Purpose:        Add our own section record to the document linked
  73.                         list.  Set up the first and last section variables.
  74.     -----------------------------------------------------------------------**/
  75.  
  76. #if !defined(powerc) && !defined(__powerc)
  77. #pragma segment Editions
  78. #endif
  79.  
  80. pascal void AddSection(SectHandle newSection, DPtr aDocument)
  81. {
  82.     if (aDocument->kind != kDocumentWindow)
  83.         return;
  84.         
  85.     /*
  86.         add the section to the document
  87.     */
  88.     aDocument->u.reg.numSections += 1;
  89.  
  90.     /*
  91.         if not NIL, add the new section to the list after the last element
  92.     */
  93.  
  94.     if (aDocument->u.reg.lastSection)
  95.         (*(aDocument->u.reg.lastSection))->fNextSection = newSection;
  96.     else
  97.         aDocument->u.reg.firstSection = newSection;
  98.  
  99.     aDocument->u.reg.lastSection = newSection;
  100.     (*newSection)->fNextSection  = nil;
  101. }
  102.  
  103. /**-----------------------------------------------------------------------
  104.         Name:         CreateSection
  105.         Purpose:        Create a new section record to hold a Publisher or
  106.                         Subscriber. Link this to the SectionRecord.
  107.     -----------------------------------------------------------------------**/
  108.  
  109. #if !defined(powerc) && !defined(__powerc)
  110. #pragma segment Editions
  111. #endif
  112.  
  113. pascal void CreateSection(SectionHandle   EMSection,
  114.                                   short           sectionID,
  115.                                   short           theStart,
  116.                                   short           theEnd,
  117.                                   DPtr            aDocument,
  118.                                   RgnHandle       theBorder)
  119.  
  120. {
  121.     SectHandle    newSection;
  122.  
  123.     if (aDocument->kind != kDocumentWindow)
  124.         return;
  125.         
  126.     /*
  127.         create a section and call AddSection to add it to the list
  128.     */
  129.     newSection = (SectHandle)NewHandle(sizeof(SectRec));
  130.  
  131.     if (newSection) {
  132.         (*newSection)->fSectionID   = sectionID;
  133.         (*newSection)->fNextSection = nil;
  134.         (*newSection)->fSectHandle  = EMSection;
  135.         (*newSection)->fStart       = theStart;
  136.         (*newSection)->fEnd         = theEnd;
  137.         (*newSection)->fCount       = theEnd - theStart;
  138.         (*newSection)->fBorderRgn   = theBorder;
  139.         (*newSection)->fDocument    = aDocument;
  140.  
  141.         /*
  142.             put a reference to our section record in the section's refCon field
  143.         */
  144.  
  145.         SetERefCon(EMSection, newSection);
  146.         AddSection(newSection, aDocument);
  147.     }
  148. }
  149.  
  150.  /**-----------------------------------------------------------------------
  151.         Name:         DeleteASection
  152.         Purpose:        Delete the section from the list.
  153.                         Called when 'Cancel Publisher/Subscriber is chosen in
  154.                         the 'Section Options' dialog.
  155.     -----------------------------------------------------------------------**/
  156.  
  157. #if !defined(powerc) && !defined(__powerc)
  158.     #pragma segment Editions
  159. #endif
  160.  
  161. pascal void DeleteASection(SectHandle sectToDelete, DPtr theDoc)
  162. {
  163.     SectHandle    currSect;
  164.     SectHandle    prevSect;
  165.  
  166.     if (theDoc->kind != kDocumentWindow)
  167.         return;
  168.  
  169.     currSect = theDoc->u.reg.firstSection;
  170.     prevSect = nil;
  171.  
  172.     while (currSect) {
  173.         if (currSect == sectToDelete) {
  174.             /*
  175.                 unlink the section from the list
  176.             */
  177.             if (prevSect)
  178.                 (*prevSect)->fNextSection = (*currSect)->fNextSection;
  179.  
  180.             if (currSect == theDoc->u.reg.firstSection)
  181.                 theDoc->u.reg.firstSection = nil;
  182.  
  183.             if (currSect == theDoc->u.reg.lastSection)
  184.                 theDoc->u.reg.lastSection = nil;
  185.         }
  186.         prevSect = currSect;
  187.         currSect = (*currSect)->fNextSection;
  188.     }
  189. }
  190.  
  191. /**-----------------------------------------------------------------------
  192.         Name:         ReadASection
  193.         Purpose:        Read in a section from disk
  194.                         Read in the rAliasType and rsectionType resources and register
  195.                         the section with the document.
  196.     -----------------------------------------------------------------------**/
  197.  
  198. #if !defined(powerc) && !defined(__powerc)
  199. #pragma segment Editions
  200. #endif
  201.  
  202. pascal void ReadASection(SectHandle aSectHandle)
  203. {
  204.     SectionHandle     aSectionHandle;
  205.     AliasHandle         anAlias;
  206.     OSErr               err;
  207.     FSSpec            myFSSpec;
  208.     Boolean            ignore;
  209.  
  210.     /*read in the rAliasType and rSectionType resources*/
  211.  
  212.     aSectionHandle = (SectionHandle)Get1Resource(rSectionType, (*aSectHandle)->fSectionID);
  213.     err            = HandToHand((Handle *)&aSectionHandle);
  214.     (*aSectHandle)->fSectHandle = aSectionHandle;
  215.     SetERefCon(aSectionHandle, aSectHandle);
  216.  
  217.     anAlias = (AliasHandle)Get1Resource(rAliasType, (*aSectHandle)->fSectionID);
  218.     err     = HandToHand((Handle *)&anAlias);
  219.     (*aSectionHandle)->alias = anAlias;
  220.  
  221.     /*now register the section*/
  222.  
  223.     err = ResolveAlias(nil, (*aSectionHandle)->alias, &myFSSpec, &ignore);
  224.     if (err) {
  225.         ShowError((StringPtr) "\pResolve Alias", err);
  226.         return;
  227.     }
  228.  
  229.     err = RegisterSection(&myFSSpec, aSectionHandle, &ignore);
  230.  
  231.     if ((err) && (err != notThePublisherWrn) && (err != multiplePublisherWrn)) {
  232.         ShowError((StringPtr) "\pRegisterSection", err);
  233.         return;
  234.     }
  235.     SetSelectionRgn(((*aSectHandle)->fDocument)->theText,
  236.                          (*aSectHandle)->fStart,
  237.                                     (*aSectHandle)->fEnd,
  238.                                     &(*aSectHandle)->fBorderRgn);
  239.     InvalRgn((*aSectHandle)->fBorderRgn);
  240. }
  241.  
  242. /**-----------------------------------------------------------------------
  243. Name:         ReadAllSectionResources
  244. Purpose:        Call the above routine to read in the resources for
  245.                 each section in the document.
  246. -----------------------------------------------------------------------**/
  247. #if !defined(powerc) && !defined(__powerc)
  248. #pragma segment Editions
  249. #endif
  250.  
  251. pascal void ReadAllSectionResources(DPtr aDoc)
  252. {
  253.     SectHandle  theSection;
  254.  
  255.     if (aDoc->kind != kDocumentWindow)
  256.         return;
  257.         
  258.     /*read in each section resource*/
  259.  
  260.     theSection = aDoc->u.reg.firstSection;
  261.     while (theSection) {
  262.         ReadASection(theSection);
  263.         theSection = (*theSection)->fNextSection;
  264.     }
  265. }
  266.  
  267. /**-----------------------------------------------------------------------
  268. Name:         ReadSectionRecords
  269. Purpose:        Read in all the 'sect' resources and form list
  270.                 of sections in the document.    This is called from the
  271.                 main read document routine.
  272. -----------------------------------------------------------------------**/
  273. #if !defined(powerc) && !defined(__powerc)
  274. #pragma segment Editions
  275. #endif
  276.  
  277. pascal void ReadSectionRecords(DPtr aDoc)
  278. {
  279.     short         theID;
  280.     SectHandle    aSectHandle;
  281.     OSErr         err;
  282.     short         theCount;
  283.  
  284.     /*read in all the 'sect' resources for our document's sections*/
  285.  
  286.     if (aDoc->kind != kDocumentWindow)
  287.         return;
  288.         
  289.     theCount = aDoc->u.reg.numSections;
  290.     if (theCount == 0)
  291.         return;
  292.  
  293.     aDoc->u.reg.numSections = 0;
  294.     for (theID = 1; theID <= theCount; theID++) {
  295.         aSectHandle = (SectHandle)Get1Resource('SECT', theID);
  296.         err = HandToHand((Handle *)&aSectHandle);
  297.  
  298.         /*now add it to the list*/
  299.  
  300.         if (aSectHandle)
  301.             AddSection(aSectHandle, aDoc);
  302.  
  303.         /*here we should recalculate the region for the bounds*/
  304.  
  305.         (*aSectHandle)->fBorderRgn = NewRgn();
  306.  
  307.         (*aSectHandle)->fDocument  = aDoc;
  308.     }
  309. }
  310.  
  311. /**-----------------------------------------------------------------------
  312.         Name:             SaveASection
  313.         Purpose:        Write out the 'sect', rAliasType and rSectionType resources
  314.                                 to file.    Called when the document is saved.
  315.     -----------------------------------------------------------------------**/
  316.  
  317. #if !defined(powerc) && !defined(__powerc)
  318. #pragma segment Editions
  319. #endif
  320.  
  321. pascal void SaveASection(SectHandle aSection, short count)
  322. {
  323.     SectionHandle  EMSection;
  324.     OSErr          err;
  325.     Handle         tempHandle;
  326.  
  327.     HLock((Handle)aSection);
  328.  
  329.     /*save this section as its component rAliasType and rSectionType resource*/
  330.     /*also save as our own section record as a 'sect' resource*/
  331.  
  332.     EMSection  = (*aSection)->fSectHandle;
  333.     tempHandle = (Handle)EMSection;
  334.     err        = HandToHand(&tempHandle);
  335.  
  336.     HLock((Handle)EMSection);
  337.     AddResource(tempHandle, rSectionType, (*EMSection)->sectionID, (StringPtr) "\p");
  338.     err = ResError();
  339.     if (err) {
  340.         ShowError((StringPtr) "\pAddResource- rSectionType", err);
  341.         return;
  342.     }
  343.  
  344.     /*now add the alias resource*/
  345.     tempHandle = (Handle)(*EMSection)->alias;
  346.     err = HandToHand(&tempHandle);
  347.     AddResource(tempHandle, rAliasType, (*EMSection)->sectionID, (StringPtr) "\p");
  348.     if (err) {
  349.         ShowError((StringPtr) "\pAddResource- rAliasType", err);
  350.         return;
  351.     }
  352.  
  353.     /*now add our own resource- for now all the record, although we only need a few fields*/
  354.     tempHandle = (Handle)aSection;
  355.     err  = HandToHand(&tempHandle);
  356.     AddResource(tempHandle, 'SECT', count, (StringPtr) "\p");
  357.     if (err) {
  358.         ShowError((StringPtr) "\pAddResource- SECT", err);
  359.         return;
  360.     }
  361.  
  362.     HUnlock((Handle)aSection);
  363.     HUnlock((Handle)EMSection);
  364. }
  365.  
  366.  /**-----------------------------------------------------------------------
  367.         Name:         SaveSections
  368.         Purpose:        Called to go down to the section list and call SaveASection
  369.                         for each one.
  370.     -----------------------------------------------------------------------**/
  371.  
  372. #if !defined(powerc) && !defined(__powerc)
  373. #pragma segment Editions
  374. #endif
  375.  
  376. pascal void SaveSections(DPtr aDocument)
  377. {
  378.     OSErr          err;
  379.     SectHandle     currSection;
  380.     short          count;
  381.  
  382.     if (aDocument->kind != kDocumentWindow)
  383.         return;
  384.  
  385.     /*go down the list and save each of the sections*/
  386.     /*the resource file is already open for writing*/
  387.  
  388.     count = 1;
  389.     err = ResError();
  390.     if (err) {
  391.         ShowError((StringPtr) "\pHOpenResFile", err);
  392.         return;
  393.     }
  394.  
  395.     /*now go down the list*/
  396.     currSection = aDocument->u.reg.firstSection;
  397.     while (currSection) {
  398.         SaveASection(currSection, count);
  399.         currSection = (*currSection)->fNextSection;
  400.         count ++;
  401.     }
  402. }
  403.  
  404. /**-----------------------------------------------------------------------
  405.     Name:         AssocAllSections
  406.     Purpose:        Associate all the sections in a document with the document.
  407.                     Called on a SaveAs.
  408. -----------------------------------------------------------------------**/
  409.  
  410. #if !defined(powerc) && !defined(__powerc)
  411. #pragma segment Editions
  412. #endif
  413.  
  414. pascal void AssocAllSections(DPtr theDoc)
  415. {
  416.     SectHandle    aSection;
  417.     SectionHandle EMSection;
  418.     OSErr         err;
  419.  
  420.     if (theDoc->kind != kDocumentWindow)
  421.         return;
  422.  
  423.     /*called by DoSaveAs.    Make sure sections are registered with this document*/
  424.     aSection = theDoc->u.reg.firstSection;
  425.     while (aSection) {
  426.         EMSection = (*aSection)->fSectHandle;
  427.         err = AssociateSection(EMSection, &theDoc->theFSSpec);
  428.         aSection  = (*aSection)->fNextSection;
  429.     }
  430. }
  431.  
  432. #endif
  433.  
  434. /**-----------------------------------------------------------------------
  435.         Name:         KeyOKinSubscriber
  436.         Purpose:        Detects arrow keys.
  437.  -----------------------------------------------------------------------**/
  438. #define kChLeft    28
  439. #define kChRight    29
  440. #define kChUp        30
  441. #define kChDown    31
  442.  
  443. #if !defined(powerc) && !defined(__powerc)
  444. #pragma segment Editions
  445. #endif
  446.  
  447. pascal Boolean KeyOKinSubscriber(char whatKey)
  448. {
  449.     return(     (whatKey==kChUp) 
  450.         ||     (whatKey==kChDown) 
  451.         ||     (whatKey==kChLeft) 
  452.         ||     (whatKey==kChRight));
  453. } /*KeyOKinSubscriber*/
  454.  
  455. #ifdef EVIL_USELESS_EDITIONS
  456. /**-----------------------------------------------------------------------
  457.         Name:         ShiftSection
  458.         Purpose:        Moves a section by howMany characters.
  459.  -----------------------------------------------------------------------**/
  460.  
  461. pascal void ShiftSection(SectHandle whichSection, short howMany)
  462. {
  463.     (*whichSection)->fStart += howMany;
  464.     (*whichSection)->fEnd   += howMany;
  465. }  /* ShiftSection */
  466.  
  467. /**-----------------------------------------------------------------------
  468. Name:         DoSectionRecalc
  469. Purpose:        Keeps track of the positions of the sections.
  470. -----------------------------------------------------------------------**/
  471.  
  472. #if !defined(powerc) && !defined(__powerc)
  473. #pragma segment Editions
  474. #endif
  475.  
  476. pascal void DoSectionRecalc(DPtr theDoc, short toAdd)
  477. {
  478.     short        theStartPos;
  479.     short        theEndPos;
  480.     short        oldSectionStart;
  481.     short        oldSectionEnd;
  482.     SectHandle   aSection;
  483.     Boolean      wasChanged;
  484.     GrafPtr      oldPort;
  485.  
  486.     if (theDoc->kind != kDocumentWindow)
  487.         return;
  488.  
  489.     /*
  490.         Work thru all sections -
  491.         1) Those spanning area of modification get modified or zapped
  492.         2) Those after get shifted back or forwards.
  493.  
  494.         Sorry it is so complicated - there's a lot of possibilities
  495.     */
  496.     theStartPos = (*(theDoc->theText))->selStart;
  497.     theEndPos   = (*(theDoc->theText))->selEnd;
  498.  
  499.     aSection = theDoc->u.reg.firstSection;
  500.     while (aSection) {
  501.         wasChanged = true;
  502.  
  503.         oldSectionEnd   = (*aSection)->fEnd;
  504.         oldSectionStart = (*aSection)->fStart;
  505.  
  506.         if (theEndPos < (*aSection)->fStart)
  507.             ShiftSection(aSection, toAdd - (theEndPos-theStartPos));
  508.         else if (theStartPos == (*aSection)->fStart)
  509.             if (theEndPos == (*aSection)->fStart)
  510.                 ShiftSection(aSection, toAdd - (theEndPos-theStartPos));
  511.             else if (theEndPos >= (*aSection)->fEnd) /* section becomes pasted text */
  512.                 (*aSection)->fEnd = (*aSection)->fStart + toAdd;
  513.             else                                                                    /* insert pasted text */
  514.                 (*aSection)->fEnd = (*aSection)->fEnd + toAdd - (theEndPos-theStartPos);
  515.         else if (theStartPos< (*aSection)->fStart)
  516.             (*aSection)->fStart = theStartPos + toAdd; /* move start to end of pasted text */
  517.         else if (theStartPos <= (*aSection)->fEnd)
  518.             if (theEndPos >= (*aSection)->fEnd) /* end of section becomes pasted text */
  519.                 (*aSection)->fEnd = theStartPos + toAdd ;
  520.             else                                                                    /* insert pasted text into section */
  521.                 (*aSection)->fEnd = (*aSection)->fEnd + toAdd - (theEndPos-theStartPos);
  522.         else
  523.             wasChanged = false;
  524.  
  525.         if (wasChanged) {
  526.             (*aSection)->fCount = (*aSection)->fEnd - (*aSection)->fStart;
  527.  
  528.             if (theDoc->u.reg.showBorders) { /* Force an update of the borders - later*/
  529.                 GetPort(&oldPort);
  530.                 SetPort(theDoc->theWindow);
  531.  
  532.                 SetSelectionRgn(theDoc->theText,
  533.                                      oldSectionStart,
  534.                                      oldSectionEnd,
  535.                                      &(*aSection)->fBorderRgn);
  536.                 InvalRgn((*aSection)->fBorderRgn);
  537.  
  538.                 SetPort(oldPort);
  539.             }
  540.         }
  541.  
  542.         aSection = (*aSection)->fNextSection;
  543.     }
  544. }  /* DoSectionRecalc */
  545.  
  546. /**-----------------------------------------------------------------------
  547. Name:         ReadAnEdition
  548. Purpose:        Read the latest version of an edition from disk.
  549. -----------------------------------------------------------------------**/
  550.  
  551. #if !defined(powerc) && !defined(__powerc)
  552. #pragma segment Editions
  553. #endif
  554.  
  555. pascal void ReadAnEdition(SectionHandle mySectHdl)
  556. {
  557.     SectHandle    aSectHandle;
  558.     EditionRefNum theRefNum;
  559.     OSErr         err;
  560.     Ptr           p;
  561.     Size          cutSize;
  562.  
  563.     p = nil;
  564.  
  565.     if (!mySectHdl) {
  566.         ShowError((StringPtr) "\pmySectHdl is NIL", 0);
  567.         return;
  568.     }
  569.  
  570.     aSectHandle = (SectHandle)GetERefCon(mySectHdl);
  571.     if (!aSectHandle) {
  572.         ShowError((StringPtr) "\paSectHandle is NIL", 0);
  573.         return;
  574.     }
  575.  
  576.     GetDateTime(&(*mySectHdl)->mdDate);
  577.  
  578.     /*read a subscriber in from disk.    Usually in response to a sectionread event*/
  579.  
  580.     if (err = OpenEdition(mySectHdl, &theRefNum)) {
  581.         ShowError((StringPtr) "\pOpenEdition in ReadAnEdition", err);
  582.         return;
  583.     }
  584.  
  585.     if (err = EditionHasFormat(theRefNum, 'TEXT', &cutSize)) {
  586.         ShowError((StringPtr) "\pEditionHasFormat in ReadAnEdition", err);
  587.         return;
  588.     }
  589.  
  590.     if (err = SetEditionFormatMark(theRefNum, 'TEXT', 0)) {
  591.         ShowError((StringPtr) "\pSetEditionFormatMark in ReadAnEdition", err);
  592.         return;
  593.     }
  594.  
  595.     /*set up a buffer for the text we're going to read in*/
  596.     p = NewPtr(cutSize);
  597.     if (!p) {
  598.         ShowError((StringPtr) "\pInsufficient memory to read edition", MemError());
  599.         return;
  600.     }
  601.  
  602.     if (err = ReadEdition(theRefNum, 'TEXT', p, &cutSize)) {
  603.         ShowError((StringPtr) "\pReadEdition", err);
  604.         return;
  605.     }
  606.  
  607.     if (err = CloseEdition(theRefNum, true)) {
  608.         ShowError((StringPtr) "\pCloseEdition", err);
  609.         return;
  610.     }
  611.  
  612.     /*
  613.         Ensure this section has a region and invalidate the old region
  614.     */
  615.  
  616.     if ((*aSectHandle)->fBorderRgn == nil)
  617.         (*aSectHandle)->fBorderRgn = NewRgn();
  618.  
  619.     SetSelectionRgn(((*aSectHandle)->fDocument)->theText,
  620.                          (*aSectHandle)->fStart,
  621.                          (*aSectHandle)->fEnd,
  622.                          &(*aSectHandle)->fBorderRgn);
  623.  
  624.     InvalRgn((*aSectHandle)->fBorderRgn);
  625.  
  626.     /*now insert the text in the right place by setting the selection range*/
  627.     /*we want this to act like paste, but without putting the contents on the clipboard*/
  628.     /*so we have to delete the current selection range and then insert our new text*/
  629.  
  630.     /*
  631.         Also fixup section info. for other moved sections
  632.     */
  633.  
  634.     TESetSelect((*aSectHandle)->fStart, (*aSectHandle)->fEnd, ((*aSectHandle)->fDocument)->theText);
  635.     DoSectionRecalc((*aSectHandle)->fDocument, cutSize);
  636.  
  637.     TEDelete(((*aSectHandle)->fDocument)->theText);
  638.     TEInsert(p, cutSize, ((*aSectHandle)->fDocument)->theText);
  639.  
  640.     /*
  641.         Now a little fix up - if the section was previously empty the
  642.         DoSectionRecalc will have put the text in before the section.
  643.         It's like that so you can type in before a subscriber in an
  644.         otherwise empty document. So now pull the start of this section
  645.         back to include the text we just added.
  646.     */
  647.  
  648.     (*aSectHandle)->fStart = (*aSectHandle)->fEnd - cutSize;
  649.  
  650.     /*
  651.         Force redraw of this region
  652.     */
  653.  
  654.     SetSelectionRgn(((*aSectHandle)->fDocument)->theText, 
  655.                          (*aSectHandle)->fStart,
  656.                          (*aSectHandle)->fEnd,
  657.                          &(*aSectHandle)->fBorderRgn);
  658.  
  659.     InvalRgn((*aSectHandle)->fBorderRgn);
  660.  
  661.     DisposPtr(p);
  662. }
  663.  
  664. /**-----------------------------------------------------------------------
  665. Name:         WriteAnEdition
  666. Purpose:        Write out the latest version of an Edition.
  667.                 Called on a Save and on selecting WriteEdition now from
  668.                 the Publisher Options dialog.
  669. -----------------------------------------------------------------------**/
  670.  
  671. #if !defined(powerc) && !defined(__powerc)
  672. #pragma segment Editions
  673. #endif
  674.  
  675. pascal void WriteAnEdition(SectionHandle mySectHdl)
  676. {
  677.     OSErr           err;
  678.     SectHandle      aSectHandle;
  679.     EditionRefNum   theRefNum;
  680.     Handle          aHandle;
  681.     FSSpecPtr       theFSSpecPtr;
  682.  
  683.     aSectHandle = (SectHandle)GetERefCon(mySectHdl);
  684.     /*alter the modification date for the section*/
  685.     GetDateTime(&(*mySectHdl)->mdDate);
  686.     /*write out the edition.  Assume that it is a publisher for now*/
  687.     /*subscribers will be opened for writing with OpenEdition*/
  688.  
  689.     if (((*aSectHandle)->fDocument)->u.reg.everSaved == false)
  690.         theFSSpecPtr = nil;
  691.     else
  692.         theFSSpecPtr = &((*aSectHandle)->fDocument)->theFSSpec;
  693.  
  694.     if (err = OpenNewEdition(mySectHdl, MPAppSig, theFSSpecPtr, &theRefNum)) {
  695.         ShowError((StringPtr) "\pOpenNewEdition", err);
  696.         return;
  697.     }
  698.  
  699.     if (err = SetEditionFormatMark(theRefNum, 'TEXT', 0)) {
  700.         ShowError((StringPtr) "\pSetEditionFormatMark", err);
  701.         return;
  702.     }
  703.  
  704.     /*now get a handle to the text to be written out*/
  705.     /*use the same start and end positions for now, increasing and decreasing*/
  706.     /*the selection will be implemented later*/
  707.  
  708.     aHandle = GetHandleToText(((*aSectHandle)->fDocument)->theText,
  709.                                       (*aSectHandle)->fStart,
  710.                                       (*aSectHandle)->fEnd);
  711.     HLock(aHandle);
  712.  
  713.     /*make sure the count is up to date*/
  714.     (*aSectHandle)->fCount = (*aSectHandle)->fEnd - (*aSectHandle)->fStart;
  715.  
  716.     if (err = WriteEdition(theRefNum, 'TEXT', *aHandle, (*aSectHandle)->fCount)) {
  717.         ShowError((StringPtr) "\pWriteEdition", err);
  718.         return;
  719.     }
  720.     HUnlock(aHandle);
  721.  
  722.     /*remember to save the section and alias records as resources later*/
  723.  
  724.     /*now close the edition*/
  725.  
  726.     if (err = CloseEdition(theRefNum, true)) {
  727.         ShowError((StringPtr) "\pCloseEdition", err);
  728.         return;
  729.     }
  730.  
  731.     /*
  732.         Clean Up
  733.     */
  734.  
  735.     DisposHandle(aHandle);
  736. }     /*WriteAnEdition*/
  737.  
  738. /**-----------------------------------------------------------------------
  739.     Name:         WriteAllEditions
  740.     Purpose:        Go down the list and call WriteAnEdition
  741. -----------------------------------------------------------------------**/
  742.  
  743. #if !defined(powerc) && !defined(__powerc)
  744. #pragma segment Editions
  745. #endif
  746.  
  747. pascal void WriteAllEditions(DPtr aDocument)
  748. {
  749.     SectHandle      aSection;
  750.     SectionHandle   EMSection;
  751.  
  752.     if (aDocument->kind != kDocumentWindow)
  753.         return;
  754.         
  755.     /*called on a Save, to write out all editions*/
  756.     aSection = aDocument->u.reg.firstSection;
  757.  
  758.     while (aSection) {
  759.         EMSection = (*aSection)->fSectHandle;
  760.         if ((*EMSection)->kind == stPublisher)
  761.             WriteAnEdition(EMSection);
  762.         aSection = (*aSection)->fNextSection;
  763.     }
  764. }
  765.  
  766. /**-----------------------------------------------------------------------
  767. Name:         DeRegisterAllSections
  768. Purpose:        Called on cancel Publisher/Subscriber and on a close.
  769. -----------------------------------------------------------------------**/
  770.  
  771. #if !defined(powerc) && !defined(__powerc)
  772. #pragma segment Editions
  773. #endif
  774.  
  775. pascal void DeRegisterAllSections(DPtr aDoc)
  776.   {
  777.         SectHandle      aSection;
  778.         SectionHandle   EMSection;
  779.         OSErr           err;
  780.  
  781.         aSection = aDoc->u.reg.firstSection;
  782.         while (aSection)
  783.             {
  784.                 EMSection = (*aSection)->fSectHandle;
  785.                 err = UnRegisterSection(EMSection);
  786.                 aSection = (*aSection)->fNextSection;
  787.             }
  788.     }
  789.  
  790. #endif
  791.  
  792. /**-----------------------------------------------------------------------
  793. Name:         GetHandleToText
  794. Purpose:        Get a handle to the current text selection.
  795.                 Used to provide a preview on Create Publisher...
  796. -----------------------------------------------------------------------**/
  797.  
  798. #if !defined(powerc) && !defined(__powerc)
  799. #pragma segment Editions
  800. #endif
  801.  
  802. pascal Handle GetHandleToText(TEHandle aTEHandle, short theStart, short theEnd)
  803. {
  804.     OSErr     err;
  805.     Handle    myHandle;
  806.     Ptr       p;
  807.  
  808.     HLock((*aTEHandle)->hText);
  809.     p  = *((*aTEHandle)->hText);
  810.     p  += theStart;
  811.     err = PtrToHand(p, &myHandle, (theEnd - theStart));
  812.     HUnlock((*aTEHandle)->hText);
  813.     return(myHandle);
  814. } /* GetHandleToText */
  815.  
  816. /**-----------------------------------------------------------------------
  817.         Name:         FindLine
  818.         Purpose:        Find the line a character is in.
  819.                         Used to find to calculate the region to use for the Publisher/
  820.                         Subscriber borders.
  821.     -----------------------------------------------------------------------**/
  822.  
  823. #if !defined(powerc) && !defined(__powerc)
  824. #pragma segment Editions
  825. #endif
  826.  
  827. pascal short FindLine(short thePos,TEHandle theTEHandle)
  828. {
  829.     short    index;
  830.     short    theFirstPos;
  831.     short    theNextPos;
  832.  
  833.     index = 0;
  834.  
  835.     do {
  836.         theFirstPos = (*theTEHandle)->lineStarts[index];
  837.         theNextPos  = (*theTEHandle)->lineStarts[index + 1];
  838.         index++;
  839.     } while (! (((thePos >= theFirstPos) && (thePos < theNextPos)) ||
  840.                     (index > (*theTEHandle)->nLines)));
  841.  
  842.     return(index);
  843. }
  844.  
  845. #ifdef EVIL_USELESS_EDITIONS
  846.  
  847. /**-----------------------------------------------------------------------
  848.         Name:         DrawSelectionRgn
  849.         Purpose:        Given a text handle and a start and end position this routine
  850.                         will draw a section border around the selected text.
  851.                         Must allow for the case when the section has no text in it-
  852.                         but we still want to show it as a published section
  853.  -----------------------------------------------------------------------**/
  854.  
  855. pascal void DrawSelectionRegion(TEHandle theTEHandle, short posStart, short posEnd)
  856. {
  857.     RgnHandle  theSelRgn;
  858.     
  859.     theSelRgn = NewRgn();
  860.     
  861.     SetSelectionRgn(theTEHandle, posStart, posEnd,&theSelRgn);
  862.     FrameRgn(theSelRgn);
  863.     
  864.     DisposeRgn(theSelRgn);
  865. } /* DrawSelectionRegion */
  866.  
  867. /**-----------------------------------------------------------------------
  868.         Name:         SetSelectionRgn
  869.         Purpose:        Given a text handle and a start and end position this routine
  870.                         will return the region which is necessary to draw a section
  871.                         border around the selected text.
  872.                         Must allow for the case when the section has no text in it-
  873.                         but we still want to show it as a published section
  874.  -----------------------------------------------------------------------**/
  875.  
  876. #if !defined(powerc) && !defined(__powerc)
  877. #pragma segment Editions
  878. #endif
  879.  
  880. pascal void SetSelectionRgn(TEHandle theTEHandle, short posStart, short posEnd, RgnHandle *theSelRgn)
  881. {
  882.     Point           theStart;
  883.     Point           theEnd;
  884.     short           startLine;
  885.     short           endLine;
  886.     Rect            theRect;
  887.     short           theLeft;
  888.     short           theRight;
  889.     short           theBottom;
  890.     short           theTop;
  891.     short           slineHeight;
  892.     short           elineHeight;
  893.     short           fontAscent;
  894.     TextStyle       theTStyle;
  895.  
  896.     /*first of all find out if the text is on the same line*/
  897.     startLine = FindLine(posStart, theTEHandle);
  898.     endLine   = FindLine(posEnd, theTEHandle);
  899.  
  900.     theStart = TEGetPoint(posStart, theTEHandle);
  901.     theEnd   = TEGetPoint(posEnd, theTEHandle);
  902.  
  903. /*
  904. Get the line height info
  905. */
  906.     TEGetStyle(posStart, &theTStyle, &slineHeight, &fontAscent, theTEHandle);
  907.     TEGetStyle(posEnd,   &theTStyle, &elineHeight, &fontAscent, theTEHandle);
  908.  
  909.     if (startLine == endLine) {
  910.         /*use the start and end points to form the rectangle and draw this into the region*/
  911.         theStart.v -= slineHeight;
  912.         Pt2Rect(theStart, theEnd, &theRect);
  913.         InsetRect(&theRect, - 1, - 1);
  914.         RectRgn(*theSelRgn, &theRect);
  915.     } else {
  916.         theLeft  = (*theTEHandle)->destRect.left;
  917.         theRight = (*theTEHandle)->destRect.right;
  918.         theTop   = theStart.v - slineHeight;
  919.         theBottom  = theEnd.v;
  920.         OpenRgn();
  921.         MoveTo(theStart.h, theStart.v - slineHeight);
  922.         LineTo(theRight, theStart.v - slineHeight);
  923.         LineTo(theRight, theEnd.v - elineHeight);
  924.         LineTo(theEnd.h, theEnd.v - elineHeight);
  925.         LineTo(theEnd.h, theEnd.v);
  926.         LineTo(theLeft, theEnd.v);
  927.         LineTo(theLeft, theStart.v);
  928.         LineTo(theStart.h, theStart.v);
  929.         LineTo(theStart.h, theStart.v - slineHeight);
  930.         CloseRgn(*theSelRgn);
  931.     }
  932.  
  933.     InsetRgn(*theSelRgn, - 2, - 2);
  934. }
  935.  
  936. /**-----------------------------------------------------------------------
  937.         Name:         ShowSectionBorders
  938.         Purpose:        Show the borders for all the sections in a document.
  939.                         Show a Publisher border in 50% gray, a subscriber in 75% gray
  940.  -----------------------------------------------------------------------**/
  941.  
  942. #if !defined(powerc) && !defined(__powerc)
  943. #pragma segment Editions
  944. #endif
  945.  
  946. pascal void ShowSectionBorders(DPtr aDoc)
  947. {
  948.     SectHandle aSection;
  949.  
  950.     if (aDoc->kind != kDocumentWindow)
  951.         return;
  952.         
  953.     PenNormal();
  954.     PenSize(3, 3);
  955.     PenPat(&qd.gray);
  956.     aSection = aDoc->u.reg.firstSection;
  957.     while (aSection) {
  958.         if ((*aSection)->fBorderRgn) {
  959.             SetSelectionRgn(((*aSection)->fDocument)->theText,
  960.                                  (*aSection)->fStart,
  961.                                  (*aSection)->fEnd,
  962.                                  &(*aSection)->fBorderRgn);
  963.  
  964.             if ((*(*aSection)->fSectHandle)->kind == stPublisher)
  965.                 PenPat(&qd.gray);
  966.             else
  967.                 PenPat(&qd.dkGray);
  968.  
  969.             FrameRgn((*aSection)->fBorderRgn);
  970.             PenNormal();
  971.         }
  972.         aSection = (*aSection)->fNextSection;
  973.     }
  974.     PenNormal();
  975. }
  976.  
  977. /**-----------------------------------------------------------------------
  978.         Name:         RecalcBorders
  979.         Purpose:        Recalculate all the borders for the sections in a document.
  980.  -----------------------------------------------------------------------**/
  981.  
  982. #if !defined(powerc) && !defined(__powerc)
  983. #pragma segment Editions
  984. #endif
  985.  
  986. pascal void RecalcBorders(DPtr aDoc, Boolean invalidate)
  987. {
  988.     SectHandle  aSection;
  989.  
  990.     if (aDoc->kind != kDocumentWindow)
  991.         return;
  992.         
  993.     /*go down the section list and recalculate all the borders*/
  994.     aSection = aDoc->u.reg.firstSection;
  995.     while (aSection) {
  996.         if ((*aSection)->fBorderRgn) {
  997.             if (invalidate)
  998.                 InvalRgn((*aSection)->fBorderRgn);
  999.  
  1000.             SetSelectionRgn(((*aSection)->fDocument)->theText,
  1001.                                  (*aSection)->fStart,
  1002.                                  (*aSection)->fEnd,
  1003.                                  &(*aSection)->fBorderRgn);
  1004.  
  1005.             if (invalidate)
  1006.                 InvalRgn((*aSection)->fBorderRgn);
  1007.         }
  1008.         aSection = (*aSection)->fNextSection;
  1009.     }
  1010. }
  1011.  
  1012. /**-----------------------------------------------------------------------
  1013.         Name:         GetSection
  1014.         Purpose:        Given a start and end of a selection- return the section
  1015.                         handle if it is in a Publisher or Subscriber.
  1016.  -----------------------------------------------------------------------**/
  1017.  
  1018. #if !defined(powerc) && !defined(__powerc)
  1019. #pragma segment Editions
  1020. #endif
  1021.  
  1022. pascal SectHandle GetSection(short theStartPos, short theEndPos, DPtr aDoc)
  1023. {
  1024.     SectHandle   foundSection;
  1025.     SectHandle   aSection;
  1026.  
  1027.     /*returns the section handle for the section between theStartPos and theEndPos*/
  1028.  
  1029.     if (aDoc->kind != kDocumentWindow)
  1030.         return nil;
  1031.         
  1032.     foundSection = nil;
  1033.  
  1034.     aSection = aDoc->u.reg.firstSection;
  1035.     while (aSection) {
  1036.         if ((theStartPos >= (*aSection)->fStart) && (theEndPos <= (*aSection)->fEnd))
  1037.             foundSection = aSection;
  1038.         aSection = (*aSection)->fNextSection;
  1039.     }
  1040.  
  1041.     return foundSection;
  1042. }
  1043.  
  1044. /**-----------------------------------------------------------------------
  1045.         Name:         DoTEPasteSectionRecalc
  1046.         Purpose:        Keeps track of the positions of the sections call before a
  1047.                     TEPaste or TEStylPaste.
  1048.  -----------------------------------------------------------------------**/
  1049.  
  1050. pascal void DoTEPasteSectionRecalc(DPtr theDoc)
  1051. {
  1052.     short toAdd;
  1053.  
  1054.     if (theDoc->kind != kDocumentWindow)
  1055.         return;
  1056.         
  1057.     toAdd = TEGetScrapLen();
  1058.     DoSectionRecalc(theDoc, toAdd);
  1059. }  /* DoTEPasteSectionRecalc */
  1060.  
  1061. /**-----------------------------------------------------------------------
  1062.         Name:         DoTEDeleteSectionRecalc
  1063.         Purpose:        Keeps track of the positions of the sections call before a
  1064.                     TEDelete.
  1065.  -----------------------------------------------------------------------**/
  1066.  
  1067. pascal void DoTEDeleteSectionRecalc(DPtr theDoc)
  1068. {
  1069.     if (theDoc->kind != kDocumentWindow)
  1070.         return;
  1071.         
  1072.     DoSectionRecalc(theDoc, 0);
  1073. }  /* DoTEDeleteSectionRecalc */
  1074.  
  1075. /**-----------------------------------------------------------------------
  1076.         Name:         DoTECutSectionRecalc
  1077.         Purpose:        Keeps track of the positions of the sections call before a
  1078.                     TECut.
  1079.  -----------------------------------------------------------------------**/
  1080.  
  1081. pascal void DoTECutSectionRecalc(DPtr theDoc)
  1082. {
  1083.     if (theDoc->kind != kDocumentWindow)
  1084.         return;
  1085.         
  1086.     DoSectionRecalc(theDoc, 0);
  1087. }  /* DoTEDeleteSectionRecalc */
  1088.  
  1089. /**-----------------------------------------------------------------------
  1090.         Name:         DoTEKeySectionRecalc
  1091.         Purpose:        Keeps track of the positions of the sections call before a
  1092.                     TECut.
  1093.  -----------------------------------------------------------------------**/
  1094.  
  1095. pascal void DoTEKeySectionRecalc(DPtr theDoc,char theChar)
  1096. {
  1097.     short     toAdd;
  1098.     short     oldStart;
  1099.  
  1100.     if (theDoc->kind != kDocumentWindow)
  1101.         return;
  1102.         
  1103.     if (!KeyOKinSubscriber(theChar)) /* is it a cursor motion key? - yes = ignore */ {
  1104.         if (theChar==8)
  1105.             if ((*(theDoc->theText))->selStart<(*(theDoc->theText))->selEnd)
  1106.                 toAdd = 0;
  1107.             else {
  1108.                 toAdd = -1;
  1109.                 oldStart = (*(theDoc->theText))->selStart;
  1110.  
  1111.                 (*(theDoc->theText))->selStart = GreaterOf(oldStart-1,0);
  1112.                 DoSectionRecalc(theDoc, 0);
  1113.                 (*(theDoc->theText))->selStart = oldStart;
  1114.             }
  1115.         else
  1116.             toAdd = 1;
  1117.  
  1118.         if (toAdd!=-1)
  1119.             DoSectionRecalc(theDoc, toAdd);
  1120.     }
  1121. }  /* DoTEKeySectionRecalc */
  1122.  
  1123. /**-----------------------------------------------------------------------
  1124.         Name:         GetEditionContainer
  1125.         Purpose:        Gets the Edition Container to put the edition into.
  1126.                         The main user interface stuff.
  1127.                         Puts up the new publisher dialog.
  1128.                         Should check kAEInteractWithUser etc.
  1129.  -----------------------------------------------------------------------**/
  1130.  
  1131. #if !defined(powerc) && !defined(__powerc)
  1132. #pragma segment Main
  1133. #endif
  1134.  
  1135. pascal OSErr GetEditionContainer(DPtr theDoc, FSSpec *theFSSpec)
  1136. {
  1137.     OSErr             err;
  1138.     NewPublisherReply myReply;
  1139.     short             theStart;
  1140.     short             theEnd;
  1141.     Handle            myHandle;
  1142.     TEHandle          myText;
  1143.  
  1144.     if (theDoc->kind != kDocumentWindow)
  1145.         return noErr;
  1146.         
  1147.     err = noErr;
  1148.  
  1149.     /*get default editionContainer to use, using last volume and folder*/
  1150.  
  1151.     myReply.container.thePart = kPartsNotUsed;
  1152.  
  1153.     err = GetLastEditionContainerUsed(&myReply.container);
  1154.  
  1155.     if (err==fnfErr)
  1156.         err = noErr;
  1157.  
  1158.     myText = theDoc->theText;
  1159.  
  1160.     theStart = (*myText)->selStart;
  1161.     theEnd   = (*myText)->selEnd;
  1162.  
  1163.     if (err==noErr) {
  1164.         /*
  1165.             Create a handle containing the text to be published for previewing -
  1166.             need to ask the user where to put the data
  1167.         */
  1168.         myHandle = GetHandleToText(myText, theStart, theEnd);
  1169.  
  1170.         myReply.usePart       = false;
  1171.         myReply.preview       = myHandle;
  1172.         myReply.previewFormat = 'TEXT';
  1173.         myReply.container.theFile.name[0] = 0; /* Want a proper prompted name here */
  1174.         HLock(myHandle);
  1175.  
  1176.         /* Should take suggested name and avoid dialog if no user interaction */
  1177.  
  1178.         err = AEInteractWithUser(kAEDefaultTimeout, nil, nil);
  1179.  
  1180.         err = NewPublisherDialog(&myReply);
  1181.         HUnlock(myHandle);
  1182.         DisposHandle(myHandle);
  1183.     }
  1184.  
  1185.     /*IF user cancelled, THEN exit from this routine*/
  1186.  
  1187.     if (err==noErr)
  1188.         if (myReply.canceled)
  1189.             err = userCanceledErr; /* User cancelled marker - replace later */
  1190.  
  1191.     if (err==noErr)
  1192.         if (myReply.replacing)
  1193.             err = FSpDelete(&myReply.container.theFile);
  1194.  
  1195.     if (err == noErr)
  1196.         *theFSSpec = myReply.container.theFile;
  1197.  
  1198.     return(err);
  1199. } /*GetEditionContainer*/
  1200.  
  1201.  
  1202. /**-----------------------------------------------------------------------
  1203.         Name:             PublishText
  1204.         Purpose:        Publishes the current selection of theDoc.
  1205.                                 The main user interface stuff.
  1206.                                 Puts up the new publisher dialog - if theFSSpec=NIL
  1207.                                 Writes the new edition out to disk.
  1208.  -----------------------------------------------------------------------**/
  1209.  
  1210. #if !defined(powerc) && !defined(__powerc)
  1211. #pragma segment Main
  1212. #endif
  1213.  
  1214. pascal OSErr PublishText(DPtr theDoc, FSSpecPtr theFSSpec)
  1215. {
  1216.     NewPublisherReply myReply;
  1217.     SectionHandle        mySectHdl;
  1218.     OSErr                 err;
  1219.     long               mysectionID;
  1220.     FSSpecPtr             pubFSSpec;
  1221.     short                 theStart;
  1222.     short                 theEnd;
  1223.     RgnHandle             theRgnHandle;
  1224.  
  1225.     if (theDoc->kind != kDocumentWindow)
  1226.         return noErr;
  1227.         
  1228.     mysectionID            = theDoc->u.reg.lastID + 1;
  1229.     theDoc->u.reg.lastID = mysectionID;
  1230.  
  1231.     /*get default editionContainer to use, using last volume and folder*/
  1232.  
  1233.     myReply.container.thePart = kPartsNotUsed;
  1234.  
  1235.     err = GetLastEditionContainerUsed(&myReply.container);
  1236.  
  1237.     if (err==fnfErr)
  1238.         err = noErr;
  1239.  
  1240.     theStart = (*theDoc->theText)->selStart;
  1241.     theEnd   = (*theDoc->theText)->selEnd;
  1242.  
  1243.     /*don't want to publish an empty section*/
  1244.  
  1245.     if (theEnd - theStart == 0)
  1246.         err = userCanceledErr;
  1247.  
  1248.     myReply.container.theFile = *theFSSpec;
  1249.  
  1250.     /*now publish this section*/
  1251.  
  1252.     if (err == noErr)
  1253.         err = CreateEditionContainerFile(&myReply.container.theFile, MPAppSig, 0);
  1254.  
  1255.     /*check IF the file has been saved, IF not set pubCFS to NIL*/
  1256.  
  1257.     if (theDoc->u.reg.everSaved == false)
  1258.         pubFSSpec = nil;
  1259.     else
  1260.         pubFSSpec = &theDoc->theFSSpec;
  1261.  
  1262.     /*get the region to encompass the selection*/
  1263.  
  1264.     theRgnHandle = NewRgn();
  1265.     SetSelectionRgn(theDoc->theText,
  1266.                          (*theDoc->theText)->selStart,
  1267.                                     (*theDoc->theText)->selEnd,
  1268.                                     &theRgnHandle);
  1269.  
  1270.     InvalRgn(theRgnHandle);
  1271.  
  1272.     /*create a publisher section*/
  1273.     if (err==noErr) {
  1274.         err = NewSection(&myReply.container,
  1275.                               pubFSSpec,
  1276.                               stPublisher,
  1277.                               mysectionID,
  1278.                               pumOnSave,
  1279.                               &mySectHdl);
  1280.  
  1281.         /*now add this section to our document list*/
  1282.  
  1283.         if (err == noErr)
  1284.             CreateSection(mySectHdl, mysectionID, theStart, theEnd, theDoc, theRgnHandle);
  1285.     }
  1286.  
  1287.     /*now write out the edition to file*/
  1288.  
  1289.     if (err==noErr)
  1290.         WriteAnEdition(mySectHdl);
  1291.  
  1292.     return(err);
  1293. } /*PublishText*/
  1294.  
  1295. /**-----------------------------------------------------------------------
  1296.         Name:         DoSubscribe
  1297.         Purpose:        Subscribe to a published section. Puts up the subscriber
  1298.                         dialog, creates and adds the new section.
  1299.  -----------------------------------------------------------------------**/
  1300.  
  1301. #if !defined(powerc) && !defined(__powerc)
  1302. #pragma segment Main
  1303. #endif
  1304.  
  1305. pascal void DoSubscribe(DPtr theDoc)
  1306. {
  1307.     NewSubscriberReply myReply;
  1308.     SectionHandle      mySectHdl;
  1309.     long               mysectionID;
  1310.     FSSpecPtr          subFSSpec; /*the fsspec for the subscriber file*/
  1311.     OSErr              err;
  1312.     short              theStart;
  1313.     short              theEnd;
  1314.  
  1315.     if (theDoc->kind != kDocumentWindow)
  1316.         return;
  1317.         
  1318.     mysectionID = theDoc->u.reg.lastID + 1;
  1319.     theDoc->u.reg.lastID = mysectionID;
  1320.     err = noErr;
  1321.  
  1322.     /*get default editionContainer to use, using last volume and folder*/
  1323.     /*  myreply.container.thePart := kPartNumberUnknown;*/
  1324.     myReply.formatsMask = kTEXTformatMask;
  1325.  
  1326.     err = GetLastEditionContainerUsed(&myReply.container);
  1327.     if (err && (err !=fnfErr)) {
  1328.         ShowError((StringPtr) "\pGetLastEditionContainerUsed", err);
  1329.         return;
  1330.     }
  1331.  
  1332.     /*put up the subscriber dialog*/
  1333.     err = NewSubscriberDialog(&myReply);
  1334.     if (err && (err !=fnfErr)) {
  1335.         ShowError((StringPtr) "\pNewSubscriberDialog", err);
  1336.         return;
  1337.     }
  1338.  
  1339.     if (myReply.canceled)
  1340.         return;
  1341.  
  1342.     /*check IF the file has been saved, IF not set pubCFS to NIL*/
  1343.     if (theDoc->u.reg.everSaved == false)
  1344.         subFSSpec = nil;
  1345.     else
  1346.         subFSSpec = &theDoc->theFSSpec;
  1347.  
  1348.     /*create a publisher section*/
  1349.     err = NewSection(&myReply.container,
  1350.                           subFSSpec,
  1351.                           stSubscriber,
  1352.                           mysectionID,
  1353.                           sumAutomatic,
  1354.                           &mySectHdl);
  1355.  
  1356.     if (err) {
  1357.         ShowError((StringPtr) "\pNewSection", err);
  1358.         return;
  1359.     }
  1360.  
  1361.     theStart = (*theDoc->theText)->selStart;
  1362.     theEnd   = (*theDoc->theText)->selEnd;
  1363.  
  1364.     /*now add this section to our document list*/
  1365.  
  1366.     CreateSection(mySectHdl, mysectionID, theStart, theEnd, theDoc, nil);
  1367.  
  1368.     /*read the subscriber in from disk*/
  1369.  
  1370.     ReadAnEdition(mySectHdl);
  1371.  
  1372. }  /*DoSubscribe*/
  1373.  
  1374. /**-----------------------------------------------------------------------
  1375.         Name:         DoSectionOptions
  1376.         Purpose:        Put up the section option dialogs for a publisher
  1377.                         or subscriber.    Handle all the various options.
  1378.                         Note that 'Find Publisher' doesn't work yet.
  1379.  -----------------------------------------------------------------------**/
  1380.  
  1381. #if !defined(powerc) && !defined(__powerc)
  1382. #pragma segment Main
  1383. #endif
  1384.  
  1385. pascal void DoSectionOptions(DPtr theDoc)
  1386. {
  1387.     OSErr               err;
  1388.     SectionOptionsReply reply;
  1389.     EditionInfoRecord   theInfo;
  1390.     SectHandle          currSection;
  1391.  
  1392.     if (theDoc->kind != kDocumentWindow)
  1393.         return;
  1394.         
  1395.     currSection = GetSection((*theDoc->theText)->selStart,
  1396.                                                      (*theDoc->theText)->selEnd,
  1397.                                                      theDoc);
  1398.  
  1399.     reply.sectionH = (*currSection)->fSectHandle;
  1400.     err = SectionOptionsDialog(&reply);
  1401.     if (!reply.canceled) {
  1402.         /*find out IF there is any action needed*/
  1403.         if (reply.action == 'read')
  1404.         /*read the latest version of a subscriber*/
  1405.             ReadAnEdition((*currSection)->fSectHandle);
  1406.         else if (reply.action == 'writ')
  1407.         /*write out the latest version of a publisher to disk*/
  1408.             WriteAnEdition((*currSection)->fSectHandle);
  1409.         else if (reply.action == 'goto') /*goto a published section*/ {
  1410.             err = GetEditionInfo((*currSection)->fSectHandle, &theInfo);
  1411.  
  1412.             if (err)
  1413.                 ShowError((StringPtr) "\pGetEditionInfo", err);
  1414.  
  1415.             err = GoToPublisherSection(&theInfo.container);
  1416.  
  1417.             if (err)
  1418.                 ShowError((StringPtr) "\pGotoPublisherSection", err);
  1419.         } else if (reply.action == 'cncl') /*cancel a publisher or subscriber*/ {
  1420.             /*unRegister the section and delete from our own list*/
  1421.             /*should have a free PROCEDURE which frees the structures*/
  1422.             /*associated with a section*/
  1423.             err = UnRegisterSection((*currSection)->fSectHandle);
  1424.             DeleteASection(currSection, theDoc);
  1425.  
  1426.             /*IF this is the ONLY publisher writing data to this edition*/
  1427.             /*we should delete the container file as well*/
  1428.         }
  1429.     }
  1430. }
  1431. #endif
  1432.